from compiler.ast import *
import compiler
import os
import explicate_ast    #actually explicate....
import sys
import flatten_ast
import uniqify_ast
import x86_IR
from sets import Set
import register_allocation
import closure_conversion_ast
import logging
import integration
from integration import *
import heapify_set
from heapify_set import *
import declassify_ast
from declassify_ast import *
import time

os.system('del -f log_compile.log')
logging.basicConfig(filename='log_compile.log',level=logging.DEBUG)


def declassify(ast):
 myvisitor = declassify_ast.DeclassifyVisitor()
 D_ast = myvisitor.preorder(ast)
 return D_ast


def uniqify(ast):
 myvisitor = uniqify_ast.UniqifyVisitor()
 U_ast = myvisitor.preorder(ast)
 return U_ast
 
def explicate(ast):
 myvisitor = explicate_ast.ExplicateVisitor()
 E_ast,exp_vars_list = myvisitor.preorder(ast)
 return E_ast,exp_vars_list

def flatten(ast):
 myvisitor = flatten_ast.FlattenVisitor()
 global All_vars_list
 global all_set
 F_ast,flt_vars_list = myvisitor.preorder(ast)
 all_set = all_set | Set(flt_vars_list) 
 return F_ast
 
def closure_conversion(ast):
 myvisitor = closure_conversion_ast.ClosureConversionVisitor()
 global All_vars_list
 global all_set
 C_ast,func_list = myvisitor.preorder(ast)
 logging.info("\n******************************************************************************************************************************************\n")
 logging.info("\n\nClose Ast>>>\n")
 logging.info(C_ast)
 return C_ast,func_list



def heapify(ast):
 locals_dict = {}
 lambda_count = 0
 heap_set = set([])
 myvisitor =  heapify_set.HeapifyVisitor()
 heap_ast = myvisitor.preorder(ast,heap_set)
 logging.info("\n******************************************************************************************************************************************\n")
 #logging.info( "\nHeapified AST: \n%s", heap_ast)


 
 return heap_ast



def make_IR(ast):
 global IR_vars_list
 global all_set
 global All_vars_list
 myvisitor = x86_IR.IRVisitor()
 IR_made,IR_vars_list = myvisitor.preorder(ast)
 all_set = all_set | Set(IR_vars_list) 
 for line in IR_made:
  print line
 return IR_made



def code_integration(close_ast,func_list):
 return integration.entry_point(close_ast, func_list)

def call_uniqify(ast):
 unique_ast = uniqify(ast)
 logging.info("UNIQIFIED AST >>>\n")
 logging.info(unique_ast)
 logging.info("\n********************************************************************************************************************************************\n")
 
 call_explicate(unique_ast)

def call_declassify():
 #print "Start code",time.time()
 comp_ast = compiler.parseFile(sys.argv[1])
 d_ast = declassify(comp_ast)
 logging.info("\n********************************************************************************************************************************************\n")
 #logging.info(d_ast)
 call_uniqify(d_ast)


def call_heapify(explicate_ast):
 heap_ast = heapify(explicate_ast) 
 return heap_ast

def call_explicate(unique_ast):
 global exp_vars_list
 global all_set
 global All_vars_list
 explicit_ast,exp_vars_list = explicate(unique_ast)
 logging.info("EXPILCATE AST\n\n")
 logging.info(explicit_ast)
 logging.info("\n********************************************************************************************************************************************\n")
 heap_ast = call_heapify(explicit_ast)
 call_closure_conversion(heap_ast)

def call_closure_conversion(explicate_ast):
 close_ast,func_list = closure_conversion(explicate_ast) 
 call_code_integration(close_ast, func_list)


def call_code_integration(close_ast,func_list):
 final_assembly = code_integration(close_ast, func_list) 
 final_write(final_assembly)


def call_flatten(explicate_ast):
 flat_ast = flatten(explicate_ast) 
 call_IR(flat_ast)
 
def call_IR(flat_ast):
 global assembly
 global IR
 #print "in IR"
 IR = make_IR(flat_ast)
 #print "assembly>>",assembly



def final_write(IR_made):
    stack_code = []  
    for line in IR_made:
      words = line.split()
    
      if(words == []):
       z=5
      else:
        if (words[0] == 'if'):
            arg = words[2]#calc_offset(words[2]) + '(%ebp)'
            stack_code.append('\tcmpl $0, ' + arg + '\n')
            stack_code.append('\tje else_label_' + words[1] + '\n')
        elif words[0] == 'ifend':
            stack_code.append('\tjmp end_label_' + words[1] + '\n')
        elif words[0] == 'else':
            stack_code.append('\telse_label_' + words[1] + ':\n')
        elif words[0] == 'elseend':
            stack_code.append('\tend_label_' + words[1] + ':\n')				    
        elif words[0] == 'while':
            arg = words[2]
            stack_code.append('\tWHILE_LABEL_'+str(words[1]) +':\n' +'\tcmpl $0, ' + arg + '\n')
            stack_code.append('\tje END_WHILE_LABEL_' + words[1] + '\n')
        elif words[0] == 'whileend':
            stack_code.append('\tjmp WHILE_LABEL_' + str(words[1])+'\n')
            stack_code.append('\tEND_WHILE_LABEL_' + words[1] + ':\n')
        else:
            stack_code.append(line)
           
   
    FILE = open(sys.argv[1].replace('.py','.s'),'w')
    FILE.writelines(stack_code)
    FILE.close()
  
  
    return 1
 


global IR
global exp_vars_list
global flt_vars_list
global IR_vars_list
exp_vars_list = []
global All_vars_list
All_vars_list = [] 

global all_set
all_set = Set([])

#call_uniqify()

call_declassify()
#print "End code",time.time()




All_vars_list = list(all_set)


